package com.fujitsu.cn.fnst.dao;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.fujitsu.cn.fnst.base.BaseDao;
import com.fujitsu.cn.fnst.base.DateUtils;
import com.fujitsu.cn.fnst.entiy.Meeting;
import com.fujitsu.cn.fnst.entiy.MeetingBook;
import com.fujitsu.cn.fnst.entiy.MeetingUse;
import com.fujitsu.cn.fnst.exception.NotOneException;
import com.fujitsu.cn.fnst.service.MeetingBookService;
import com.fujitsu.cn.fnst.service.MeetingService;
import com.itextpdf.text.xml.simpleparser.EntitiesToSymbol;

@Repository
public class MeetingUseDao extends BaseDao<MeetingUse> {
	private final static int used = 1;
	private final static int unused = 0;
	@Resource
	private MeetingBookService meetingBookService;
	@Resource
	private MeetingService meetingService;
	private static final Map<Float, String> map = new HashMap<Float, String>();
	static {
		map.put(8f, "eight");
		map.put(8.5f, "eightHalf");
		map.put(9f, "nine");
		map.put(9.5f, "nineHalf");
		map.put(10f, "ten");
		map.put(10.5f, "tenHalf");
		map.put(11f, "eleven");
		map.put(11.5f, "elevenHalf");
		map.put(12f, "twelve");
		map.put(12.5f, "twelveHalf");
		map.put(13f, "thirteen");
		map.put(13.5f, "thirteenHalf");
		map.put(14f, "forteen");
		map.put(14.5f, "forteenHalf");
		map.put(15f, "fifteen");
		map.put(15.5f, "fifteenHalf");
		map.put(16f, "sixteen");
		map.put(16.5f, "sixteenHalf");
		map.put(17f, "seventeen");
		map.put(17.5f, "seventeenHalf");
		map.put(18f, "eightteen");

	}

	/***
	 * @return true 表示不可以使用
	 * **/
	public boolean checkMeetingisVaild(Date startDate, Date endDate,
			int meetingRoom) {
		boolean isVaild = false;
		Session session = getSession();
		Criteria criteria = session.createCriteria(MeetingUse.class);
		criteria.add(Restrictions.eq("meetingId", meetingRoom)).add(
				Restrictions.eq("date", startDate));
		MeetingUse use = null;
		try {
			use = query4One(criteria);

		} catch (NotOneException e) {
			releaseSession(session);
			return false;
		}
		List<Float> list = DateUtils.getFormattedDate(startDate, endDate);
		isVaild = !check(use, list);

		return isVaild;
	}

	/**
	 * @return true 未占用
	 * **/
	private boolean check(MeetingUse use, List<Float> list) {
		for (float f : list) {
			String value = map.get(f);
			try {
				Field field = MeetingUse.class.getDeclaredField(value);
				field.setAccessible(true);
				if (field.get(use) != null && (Integer) field.get(use) == used) {
					return false;
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	public void bookMeetingRoom(Date startTime, Date endTime, int meetingId) {
		Session session = getSession();
		Criteria criteria = session.createCriteria(MeetingUse.class);
		criteria.add(Restrictions.eq("meetingId", meetingId)).add(
				Restrictions.eq("date", startTime));
		MeetingUse use = null;
		try {
			use = query4One(criteria);

		} catch (NotOneException e) {
			Meeting meeting = meetingService.find(meetingId);
			String name = meeting == null ? "无名" : meeting.getMeetingName();
			use = new MeetingUse(name, meetingId, startTime, unused, unused,
					unused, unused, unused, unused, unused, unused, unused,
					unused, unused, unused, unused, unused, unused, unused,
					unused, unused, unused, unused, unused);
		}
		releaseSession(session);
		List<Float> list = DateUtils.getFormattedDate(startTime, endTime);
		use = fillTime(use, list, used);
		getHibernateTemplate().saveOrUpdate(use);
	}

	private MeetingUse fillTime(MeetingUse use, List<Float> list, int value) {
		for (float f : list) {
			String valuetemp = map.get(f);
			try {
				Field field = MeetingUse.class.getDeclaredField(valuetemp);
				field.setAccessible(true);
				field.set(use, value);
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return use;

	}

	public void deleteBook(MeetingBook book) {
		Session session = getSession();
		Criteria criteria = session.createCriteria(MeetingUse.class);
		criteria.add(Restrictions.eq("meetingId", book.getMeetingId())).add(
				Restrictions.eq("date", book.getBookStartTime()));
		MeetingUse use = null;
		try {
			use = query4One(criteria);

		} catch (NotOneException e) {
			e.printStackTrace();
			releaseSession(session);
			return;
		}
		releaseSession(session);
		List<Float> list = DateUtils.getFormattedDate(book.getBookStartTime(),
				book.getBookEndTime());
		use = fillTime(use, list, unused);
		getHibernateTemplate().saveOrUpdate(use);

	}

	public MeetingBook meetingModel(int meetingId, String amount) {
		float amountFloat = Float.parseFloat(amount.trim());
		Session session = getSession();
		Criteria criteria = null;
		Date now = new Date();
		MeetingUse meetingUse = null;
		boolean changed = false;
		float beginTime = 0.0f;
		Meeting meeting = meetingService.find(meetingId);
		MeetingBook book = new MeetingBook(meeting.getMeetingName(), "-1",
				meetingId, -1, now, now, now, now, amountFloat, 0);
		book.setId(meetingId);
		while (true) {
			criteria = session.createCriteria(MeetingUse.class);
			criteria.setMaxResults(1);
			criteria.add(Restrictions.eq("meetingId", meetingId))
					.add(Restrictions.le("date", now))
					.add(Restrictions.ge("date", now));
			try {
				meetingUse = query4One(criteria);
				beginTime = hasEnoughTime(meetingUse, amountFloat,!changed);
				if (beginTime != -1) {
					break;
				} else {
					changed = true;
					now = DateUtils.getBeginTimeOfNextDay(meetingUse.getDate());
				}
			} catch (NotOneException e) {
				meetingUse=null;
				break;
			}
		}
		releaseSession(session);
		if (meetingUse == null) {
			// 表示有空的一天
			book.setBookStartTime(DateUtils.add(now, 8));
			book.setBookEndTime(DateUtils.add(now, 8+amountFloat));
		} else {
			book.setBookStartTime(DateUtils.add(now, beginTime));
			book.setBookEndTime(DateUtils.add(now, beginTime+amountFloat));
		}
		return book;
	}

	// TODO
	@SuppressWarnings("unchecked")
	public List<Meeting> timeModel(String date, String beginTime,
			String endTime, String amount) throws ParseException {
		String dateBegin = date + " " + beginTime.toUpperCase();
		String dateEnd = date + " " + endTime.toUpperCase();
		Date beginDate = DateUtils.getFormattedStartTime(getDateformat().parse(
				dateBegin));
		Date endDate = DateUtils.getFormattedEndTime(getDateformat().parse(
				dateEnd));
		int amountInt = Integer.parseInt(amount.trim());
		Session session = getSession();
		String sql = " select distinct meetingId from MeetingUse where date=? "
				+ isUnUsed(beginDate, endDate);
		Query query = session.createQuery(sql);
		query.setDate(0, beginDate);
		List<Integer> list1 = query.list();
		sql = "select distinct meetingId from MeetingUse where date=?";
		query = session.createQuery(sql);
		query.setDate(0, beginDate);
		List<Integer> list2 = query.list();
		sql = "select  id from Meeting ";
		query = session.createQuery(sql);
		List<Integer> list3 = query.list();
		list3.removeAll(list2);
		list3.addAll(list1);
		releaseSession(session);
		List<Meeting> meetings = new ArrayList<Meeting>();
		for (Integer i : list3) {
			Meeting meeting = meetingService.find(i);
			if (meeting != null) {
				meetings.add(meeting);
			}
		}
		return meetings;
	}

	/**
	 * 段时间内没有被使用
	 * **/
	public Criteria isUnUsed(Criteria criteria, Date dateBegin, Date dateEnd) {
		List<Float> list = DateUtils.getFormattedDate(dateBegin, dateEnd);
		for (Float f : list) {
			criteria = isUnUsed(criteria, map.get(f));
		}
		return criteria;
	}

	/**
	 * 没有被使用
	 * **/
	public Criteria isUnUsed(Criteria criteria, String propertyName) {
		return criteria.add(Restrictions.or(Restrictions.isNull(propertyName),
				Restrictions.eq(propertyName, unused)));
	}

	/**
	 * 段时间内没有被使用
	 * **/
	public String isUnUsed(Date dateBegin, Date dateEnd) {
		List<Float> list = DateUtils.getFormattedDate(dateBegin, dateEnd);
		StringBuilder sb = new StringBuilder();
		for (Float f : list) {
			sb.append(isUnUsed(map.get(f)));
		}
		return sb.toString();
	}

	/**
	 * 没有被使用
	 * **/
	public String isUnUsed(String propertyName) {
		return " and ( " + propertyName + " is null or " + propertyName + " ="
				+ unused + " )";
	}

	public MeetingUse getMeetingUse(int meetingId, Date date) {
		Session session = getSession();
		Criteria criteria = session.createCriteria(MeetingUse.class);
		criteria.add(Restrictions.eq("meetingId", meetingId)).add(
				Restrictions.eq("date", date));
		List<MeetingUse> meetingUses = query(criteria);
		if (meetingUses == null || meetingUses.size() == 0) {
			Meeting meeting = meetingService.find(meetingId);
			String name = meeting == null ? "无名" : meeting.getMeetingName();
			return new MeetingUse(name, meetingId, date, unused, unused,
					unused, unused, unused, unused, unused, unused, unused,
					unused, unused, unused, unused, unused, unused, unused,
					unused, unused, unused, unused, unused);
		}
		return meetingUses.get(0);
	}

	public List<MeetingUse> getMeetingUses(int right, Date date) {
		List<Meeting> meetings = meetingService
				.findByFilter("and meetingRight<=" + right);
		List<MeetingUse> uses = new ArrayList<MeetingUse>();
		for (Meeting meeting : meetings) {
			MeetingUse meetingUse = getMeetingUse(meeting.getId(), date);
			uses.add(meetingUse);
		}
		return uses;
	}

	private float hasEnoughTime(MeetingUse meetingUse, float amount,
			boolean checkTime) {
		if (meetingUse == null) {
			return 8;
		}
		float count = 0f;
		Date now = new Date();
		float f = DateUtils.getNow(now);
		for (float f1=8.0f;f1<=17.5f;f1+=0.5f) {
			try {
				String value=map.get(f1);
				if (checkTime && f1 < f) {
					f1=f;
					continue;
				}
				Field field = MeetingUse.class.getDeclaredField(value);
				field.setAccessible(true);
				if ((Integer) field.get(meetingUse) == unused) {
					count += 0.5f;
				} else {
					count = 0f;
				}
				if (count >= amount) {
					return f1 - amount;
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		return -1;
	}
}
